package com.nbsaas.boot;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.LongAdder;

/**
 * 通用性能测试工具，用于测试 LongHandle 实现的性能。
 *
 * 可测指标：
 *  - 单线程性能（encode/decode 平均耗时）
 *  - 多线程性能（QPS）
 */
public class LongHandleBenchmark {

    private static final int WARMUP_ROUNDS = 10_000;  // JIT 预热次数
    private static final int TEST_ROUNDS = 1_000_000; // 正式测试次数
    private static final int THREADS = Runtime.getRuntime().availableProcessors();

    public static void main(String[] args) throws Exception {
        System.out.println("CPU 核心数: " + THREADS);
        LongHandle handle = new FeistelLongHandle("benchmark-key", 12);
        runBenchmark("FeistelLongHandle", handle);
    }

    public static void runBenchmark(String name, LongHandle handle) throws Exception {
        System.out.printf("==== 测试 [%s] ====%n", name);
        warmup(handle);
        testSingleThread(handle);
        testMultiThread(handle);
    }

    /** JIT 预热（防止第一次慢） */
    private static void warmup(LongHandle handle) {
        Random random = new Random();
        for (int i = 0; i < WARMUP_ROUNDS; i++) {
            long num = random.nextLong();
            String s = handle.encode(num);
            handle.decode(s);
        }
        System.out.println("预热完成 ✅");
    }

    /** 单线程测试 encode/decode 性能 */
    private static void testSingleThread(LongHandle handle) {
        Random random = new Random(12345);
        long startEncode = System.nanoTime();
        for (int i = 0; i < TEST_ROUNDS; i++) {
            handle.encode(random.nextLong());
        }
        long encodeTime = System.nanoTime() - startEncode;

        random.setSeed(54321);
        long startDecode = System.nanoTime();
        for (int i = 0; i < TEST_ROUNDS; i++) {
            String s = handle.encode(random.nextLong());
            handle.decode(s);
        }
        long decodeTime = System.nanoTime() - startDecode;

        double avgEncodeNs = (double) encodeTime / TEST_ROUNDS;
        double avgDecodeNs = (double) decodeTime / TEST_ROUNDS;
        double qpsEncode = 1_000_000_000.0 / avgEncodeNs;
        double qpsDecode = 1_000_000_000.0 / avgDecodeNs;

        System.out.printf("单线程 encode: 平均 %.2f ns/op (%.2f M ops/sec)%n",
                avgEncodeNs, qpsEncode / 1_000_000);
        System.out.printf("单线程 decode: 平均 %.2f ns/op (%.2f M ops/sec)%n",
                avgDecodeNs, qpsDecode / 1_000_000);
    }

    /** 多线程并发性能测试 */
    private static void testMultiThread(LongHandle handle) throws Exception {
        System.out.printf("开始多线程测试（%d threads, %d 次）...%n", THREADS, TEST_ROUNDS);

        ExecutorService pool = Executors.newFixedThreadPool(THREADS);
        LongAdder counter = new LongAdder();
        Random random = new Random();
        int totalTasks = TEST_ROUNDS;
        long start = System.nanoTime();

        for (int i = 0; i < totalTasks; i++) {
            long num = random.nextLong();
            pool.submit(() -> {
                String s = handle.encode(num);
                handle.decode(s);
                counter.increment();
            });
        }

        pool.shutdown();
        pool.awaitTermination(10, TimeUnit.MINUTES);

        long time = System.nanoTime() - start;
        double sec = time / 1_000_000_000.0;
        double qps = counter.sum() / sec;

        System.out.printf("多线程总耗时: %.2f 秒，总操作数: %d，QPS: %.2f ops/sec%n",
                sec, counter.sum(), qps);
    }
}
